from urllib.request import urlopen
import requests
import uuid
import pyaes

PRIVATE_API_URL = "https://api.tidalhifi.com/v1/%s"

class TidalAPI:
  def __init__(self):
    self.session = requests.Session()
    self.session_id = None
    self.country_code = "US" # should we set this to what the server says?

  def call_private_api(
      self, path, params = {}, headers = {},
      post = False, form = False
  ):
    url = PRIVATE_API_URL % path

    params["countryCode"] = self.country_code

    if self.session_id != None:
      headers["X-Tidal-SessionId"] = self.session_id
      #params["sessionId"] = self.session_id

    args = {
      "params": params,
      "headers": headers
    }
    if form:
      args["data"] = form

    response = None
    if post:
      response = self.session.post(url, **args)
    else:
      response = self.session.get(url, **args)

    json = response.json()
    if "status" in json and json["status"] == 404:
      raise 'not found'

    return response

  def login(self, username, password):
    # more info about tokens: https://github.com/arnesongit/plugin.audio.tidal2/blob/master/resources/lib/koditidal.py#L781
    # if the link is dead: https://ghostbin.com/paste/y9g6e
    token = "BI218mwp9ERZ3PFI"

    data = self.call_private_api(
      "login/username",
      post = True,
      params = {"token": token},
      form = {
        "username": username,
        "password": password,
        "clientUniqueKey": str(uuid.uuid4()).replace('-', '')[16:]
      }
    ).json()

    if "status" in data:
      if data["status"] == 401:
        raise 'username or password is wrong'
      else:
        raise 'unknown error getting session id'
    else:
      self.session_id = data["sessionId"]
      #self.user_id = data["userId"]
      #self.country_code = data["countryCode"]
      return data

  def get_user_data(self, user_id):
    data = self.call_private_api("users/%i" % user_id).json()
    if "status" in data and not data["status"] == 200:
      raise 'unknown error when getting profile'

    return data

  def get_stream_info(self, track_id, quality):
    return self.call_private_api(
      "tracks/%i/streamUrl" % track_id,
      params = {"soundQuality": quality}
    )

  def get_track_data(self, track_id):
    return self.call_private_api("tracks/%i" % track_id)

  def get_album_data(self, album_id):
    return self.call_private_api("albums/%i" % album_id)
  def get_album_tracks_data(self, album_id):
    print(album_id)
    return self.call_private_api("albums/%i/tracks" % album_id)

  def get_artist_data(self, artist_id):
    return self.call_private_api("artists/%i" % artist_id)
  def get_artist_albums_data(self, artist_id):
    return self.call_private_api("artists/%i/albums" % artist_id)

  def get_search_data(self, search_query, field, limit = 50):
    params = {"query": search_query, "limit": limit}
    if field not in ['artists', 'albums', 'playlists', 'tracks']:
      raise ValueError('Unknown field `%s`' % field)
    return self.call_private_api(
      'search/%s' % field,
      params = params
    )
